import asyncio
import logging
import re

import requests

from msg_handler_impl.handler import SingleMsgHandlerBase
from util import msg_send_utils

logger = logging.getLogger()

QRY_PATTERN = re.compile("(出行|政策|出行政策) (?P<from>[^\\s]+) (?P<to>[^\\s]+)")


async def async_request(url, method: str = 'get', *args, **kwargs):
    logger.info("%s: %s", method.upper(), url)
    return requests.request(method=method, url=url, *args, **kwargs)


async def get_all_cities() -> list:
    all_cities = []
    url_city_list = 'https://r.inews.qq.com/api/trackmap/citylist?'
    city_list_raw = await async_request(url_city_list)
    response = city_list_raw.json()
    if response['status'] == 0 and response['message'] == "success":
        for province in response['result']:
            for city in province['list']:
                all_cities.append(city['name'])
    else:
        raise RuntimeError("获取城市信息失败， resp: %s" % response.text)
    return all_cities


async def get_policy(_from: str, _to: str) -> str:
    _from_id, _to_id = None, None
    url_city_list = 'https://r.inews.qq.com/api/trackmap/citylist?'
    city_list_raw = await async_request(url_city_list)
    city_list = city_list_raw.json()
    msg = ""
    if city_list['status'] == 0 and city_list['message'] == "success":
        for province in city_list['result']:
            for city in province['list']:
                if _from == city['name']:
                    _from_id = city['id']
                if _to == city['name']:
                    _to_id = city['id']

    url_get_policy = f"https://r.inews.qq.com/api/trackmap/citypolicy?&city_id={_from_id},{_to_id}"

    policy_raw = await async_request(url_get_policy)
    policy = policy_raw.json()
    if policy['status'] == 0 and policy['message'] == "success":
        data_leave = policy['result']['data'][0]
        data_to = policy['result']['data'][1]
        if _from == _to and data_leave['leave_policy'].strip() == data_to['back_policy'].strip():
            msg += f"{_from}出入政策：\n"
            msg += f"{data_to['back_policy'].strip()}（于{data_to['back_policy_date']}更新）"
            msg += "\n"
        else:
            msg += f"{_from}离开政策：\n{data_leave['leave_policy'].strip()}（于{data_leave['leave_policy_date']}更新）"
            msg += "\n\n"
            msg += "-" * 50
            msg += "\n\n"
            msg += f"{_to}进入政策：\n{data_to['back_policy'].strip()}（于{data_to['back_policy_date']}更新）"
            msg += "\n"
        msg += f"{_to}酒店政策：\n{data_to['stay_info'].strip()}"
        msg += "\n\n"
        msg += "-" * 50
        msg += "\n\n"
        msg += "免责声明：以上所有数据来源于https://news.qq.com/hdh5/sftravel.htm#/"
    else:
        msg += "政策请求错误" + policy_raw.text
    return msg


def _get_sender_id(_msg: dict):
    return _msg['sender']["id"] if _msg["type"] == "FriendMessage" else _msg['sender']['group']["id"]


async def send_travel_policy(msg: dict, ctx: ..., _from, to):
    msg_chain = []
    resp = await get_policy(_from, to)
    if "错误" not in resp:
        msg_chain.append({
            "type": "Plain",
            "text": resp
        })
    else:
        for line in resp.split("\n"):
            line = line.strip()
            msg_chain.append({
                "type": "Plain",
                "text": line
            })
    try:
        cfg = ctx.cfg
        if msg["type"] == "FriendMessage":
            msg_send_utils.send_friend_msg(cfg["session"], _get_sender_id(msg), msg_chain)
        else:
            msg_send_utils.send_group_msg(cfg["session"], _get_sender_id(msg), msg_chain)
        return "success"
    except Exception as e:
        logger.exception(e)


class TravelPolicyMsgHandler(SingleMsgHandlerBase):
    """
    源项目： https://github.com/SlightDust/travelpolicy_HoshinoBot/blob/master/travelpolicy_HoshinoBot.py
    """

    def can_handle(self, msg: dict, *args, **kwargs):
        msg_type = msg.get('type')
        return msg_type in ["FriendMessage", "GroupMessage"]

    def handle(self, msg: dict, ctx, *args, **kwargs):
        msg_chain = msg['messageChain']
        # Source类型永远为chain的第一个元素: {'type': 'Source', 'id': 26675, 'time': 1661589588}
        source_msg = msg_chain[0]
        logger.info(source_msg)
        event_loop = asyncio.get_event_loop()
        for single_msg in msg_chain:
            single_msg_type = single_msg['type']
            if single_msg_type == 'Plain':
                content: str = single_msg['text'].strip()
                if content in ["/出行城市", "出行城市"]:
                    cfg = ctx.cfg
                    all_cities = event_loop.run_until_complete(get_all_cities())
                    send_msg_chain = [{
                        "type": "Plain",
                        "text": ",".join(all_cities)
                    }]
                    if msg["type"] == "FriendMessage":
                        msg_send_utils.send_friend_msg(cfg["session"], _get_sender_id(msg), send_msg_chain)
                    else:
                        msg_send_utils.send_group_msg(cfg["session"], _get_sender_id(msg), send_msg_chain)
                else:
                    matcher = QRY_PATTERN.match(content.strip())
                    if matcher:
                        _from, _to = matcher.group("from"), matcher.group("to")
                        event_loop.run_until_complete(send_travel_policy(msg, ctx, _from, _to))
